package com.gillion.tms.service.impl;

import com.gfa4j.mybatis.mapper.BaseMapper;
import com.gfa4j.mybatis.service.impl.BaseServiceImpl;
import com.gfa4j.security.data.entity.ITable;
import com.gfa4j.security.domain.IUser;
import com.gfa4j.security.function.service.UserService;
import com.gfa4j.utils.UserUtils;

import com.gillion.business.mapper.SysUserMapper;
import com.gillion.business.model.SysAclTable;
import com.gillion.business.model.SysRoleAcl;
import com.gillion.tms.entity.DataPermission;
import com.gillion.tms.entity.Table;
import com.gillion.tms.entity.User;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * User: liaowj
 * Date: 2015/3/13
 * Time: 18:16
 */
@Service("userService")
public class UserServiceImpl extends BaseServiceImpl implements UserService, InitializingBean {

    @Autowired
    private DataSource   dataSource;
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private SysUserMapper sysUserMapper;


    //    @Override
    public BaseMapper getMapper() {
        return sysUserMapper;
    }


    @Override
    public IUser findByUsername(String username) {
        final User user = jdbcTemplate.queryForObject("SELECT * FROM sys_user WHERE USERNAME = ?", BeanPropertyRowMapper.newInstance(User.class), username);
        final List<String> hasPermissionUrlPatterns = jdbcTemplate.queryForList("SELECT URL FROM sys_resource WHERE RESOURCE_ID IN (SELECT RESOURCE_ID FROM sys_role_resource WHERE ROLE_ID IN (SELECT ROLE_ID FROM sys_role_user WHERE USER_ID = (SELECT USER_ID FROM sys_user WHERE USERNAME = ?)))", String.class, username);
        user.setHasPermissionUrlPatterns(Lists.newArrayList(hasPermissionUrlPatterns));
        return user;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    @Override
    public List<String> getAnonymousPermissionUrlPatterns() {
        return jdbcTemplate.queryForList("SELECT URL  FROM sys_resource WHERE RESOURCE_ID IN (SELECT RESOURCE_ID FROM sys_role_resource WHERE ROLE_ID = ?)", String.class, UserUtils.ANONYMOUS_ROLE_ID);
    }


    //@Cacheable("test")
    @Override
    public Collection<ITable> getAnonymousDataPermissionTables() {
        List<SysAclTable> sysAclTables = Lists.newArrayList();
        List<SysRoleAcl> sysRoleAcls = Lists.newArrayList();
        jdbcTemplate.query("SELECT * FROM SYS_ACL_TABLE ", (rs)->{
            SysAclTable sysAclTable = new SysAclTable();
            sysAclTable.setAclTableId(rs.getString("ACL_TABLE_ID"));
            sysAclTable.setAclMode(rs.getByte("ACL_MODE"));
            sysAclTable.setTableName(rs.getString("TABLE_NAME"));
            sysAclTables.add(sysAclTable);
        });
        jdbcTemplate.query("SELECT * FROM SYS_ROLE_ACL WHERE ROLE_ID = ?", (rs)->{
            SysRoleAcl sysRoleAcl = new SysRoleAcl();
            sysRoleAcl.setAclTableId(rs.getString("ACL_TABLE_ID"));
            sysRoleAcl.setAclConditionId(rs.getString("ACL_CONDITION_ID"));
            sysRoleAcl.setCondition(rs.getString("CONDITION"));
            sysRoleAcl.setConditionSql(rs.getString("CONDITION_SQL"));
            sysRoleAcl.setCrudType(rs.getByte("CRUD_TYPE"));
            sysRoleAcls.add(sysRoleAcl);
        }, UserUtils.ANONYMOUS_ROLE_ID);

        List<Table> tables = Lists.newArrayList();
        Map<String,ITable> tablesMap = Maps.newHashMap();
        for(SysAclTable sysAclTable:sysAclTables){
            Table table = new Table(sysAclTable);
            tablesMap.put(sysAclTable.getAclTableId(),table);
        }
        for (SysRoleAcl sysRoleAcl:sysRoleAcls){
            if (tablesMap.containsKey(sysRoleAcl.getAclTableId())){
                DataPermission dataPermission = new DataPermission(sysRoleAcl);
                tablesMap.get(sysRoleAcl.getAclTableId()).getDataPermisssions().add(dataPermission);
            }
        }
        return tablesMap.values();
    }
}
